/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the oil4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.telecom.oil.smart.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.telecom.oil.common.core.constant.CacheConstants;
import com.telecom.oil.common.core.constant.SecurityConstants;
import com.telecom.oil.common.core.exception.BusinessException;
import com.telecom.oil.common.security.util.SecurityUtils;
import com.telecom.oil.smart.api.dto.RecognizeReq;
import com.telecom.oil.smart.api.entity.OilOrgInfo;
import com.telecom.oil.smart.api.entity.OilUser;
import com.telecom.oil.smart.api.enums.RecognizeStatusEnum;
import com.telecom.oil.smart.api.vo.OilUserExcelVo;
import com.telecom.oil.smart.api.vo.OilUserSimpleVo;
import com.telecom.oil.smart.api.vo.OilUserVo;
import com.telecom.oil.smart.mapper.OilUserMapper;
import com.telecom.oil.smart.service.OilOrgInfoService;
import com.telecom.oil.smart.service.OilUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 用户信息表
 *
 * @author jianghuai
 * @date 2022-10-18 14:39:08
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OilUserServiceImpl extends ServiceImpl<OilUserMapper, OilUser> implements OilUserService {

	@Value("${weixin.appId}")
	private String appId;

	@Value("${weixin.appSecret}")
	private String appSecret;

	private final OilOrgInfoService oilOrgInfoService;

	@Override
	public String recognize(RecognizeReq req) {
		com.telecom.oil.common.security.service.OilUser user = SecurityUtils.getUser();
		OilUser oilUser = this.getById(user.getId());
		if (oilUser == null) {
			// throw new Exception("当前用户不存在");
		}
		oilUser.setRecognizeStatus(1);
		this.updateById(oilUser);
		return oilUser.getUserName();
	}

	@Override
	public OilUser weixinLogin(String code) {

		// 1.微信code登录
		String url = String.format(SecurityConstants.MINI_APP_AUTHORIZATION_CODE_URL, appId, appSecret, code);
		String result = HttpUtil.get(url);
		JSONObject jsonObject = JSON.parseObject(result);
		String openid = jsonObject.getString("openid");
		if (StringUtils.isEmpty(openid)) {
			throw new BusinessException("请重新授权登录");
		}
		String sessionKey = jsonObject.getString("session_key");
		log.debug("微信openId:{},微信session_key:{}", openid, sessionKey);
		OilUser oilUser = null;
		oilUser = this.findByOpenId(openid);
		if (oilUser == null) {
			// 新建用户
			oilUser = new OilUser();
			oilUser.setRecognizeStatus(0);
			oilUser.setPhone("");
			oilUser.setAvatar("");
			oilUser.setUserName("微信用户");
			oilUser.setNickName("微信用户");
			oilUser.setCompany("才华有限公司");
			oilUser.setOpenId(openid);
			this.save(oilUser);
		}
		return oilUser;

		// 2.微信手机号授权登录
		// String url1 = String.format(SecurityConstants.MINI_APP_GET_ACCESSTOKEN_URL,
		// appId, appSecret);
		// String result1 = HttpUtil.get(url1);
		// JSONObject jsonObject1 = JSON.parseObject(result1);
		// String accessToken = jsonObject1.getString("access_token");
		// if(StringUtils.isEmpty(accessToken)){
		// throw new BusinessException("登陆失败");
		// }
		// Map<String, Object> hashMap = new HashMap<String, Object>();
		// hashMap.put("access_token", accessToken);
		// hashMap.put("code", code);
		// String result2 = HttpUtil.post(SecurityConstants.MINI_APP_GET_PHONENUMBER_URL,
		// hashMap);
		// JSONObject jsonObject2 = JSON.parseObject(result2);
		// String phone = jsonObject2.getString("purePhoneNumber");
		// if(StringUtils.isEmpty(phone)){
		// throw new BusinessException("获取手机号失败");
		// }
		// UserInfo userInfo = null;
		// userInfo = this.findByPhoneNumber(phone);
		// if(userInfo == null){
		// //新建用户
		// userInfo = new UserInfo();
		// userInfo.setRecognizeStatus(0);
		// userInfo.setPhoneNumber(phone);
		// userInfo.setAvatarUrl("");
		// userInfo.setUserName("微信用户");
		// userInfo.setNickName("微信用户");
		// this.save(userInfo);
		// }
		// return userInfo;
	}

	@Override
	public void identifyApply(Long id) {
		OilUser oilUser = this.getById(id);
		if (oilUser == null) {
			throw new BusinessException("未找到该用户");
		}
		oilUser.setRecognizeStatus(RecognizeStatusEnum.TOBE_RECOGNIZE.getCode());
		this.updateById(oilUser);
	}

	@Override
	public List<OilUserExcelVo> listUser() {
		List<OilUser> userList = this.list(Wrappers.emptyWrapper());
		// 转换成execl 对象输出
		return userList.stream().map(user -> {
			OilUserExcelVo oilUserExcelVo = new OilUserExcelVo();
			BeanUtil.copyProperties(user, oilUserExcelVo);
			switch (user.getRecognizeStatus()) {
				case 0:
					oilUserExcelVo.setRecognizeStatus(RecognizeStatusEnum.UN_RECOGNIZE.getDescription());
					break;
				case 1:
					oilUserExcelVo.setRecognizeStatus(RecognizeStatusEnum.TOBE_RECOGNIZE.getDescription());
					break;
				case 2:
					oilUserExcelVo.setRecognizeStatus(RecognizeStatusEnum.RECOGNIZED.getDescription());
					break;
				case 3:
					oilUserExcelVo.setRecognizeStatus(RecognizeStatusEnum.FAIL_RECOGNIZE.getDescription());
					break;
			}

			OilOrgInfo orgInfo = oilOrgInfoService.getById(user.getDeptId());
			if (orgInfo != null) {
				oilUserExcelVo.setDeptName(orgInfo.getDeptName());
			}

			return oilUserExcelVo;
		}).collect(Collectors.toList());
	}

	@Override
	public OilUserVo getUserInfo(Long id) {
		OilUser userInfo = Optional.ofNullable(this.getById(id)).orElseThrow(() -> new BusinessException("未找到此用户"));
		return OilUserVo.builder()
				.avatar(userInfo.getAvatar())
				.phone(userInfo.getPhone())
				.userName(userInfo.getUserName())
				.nickName(userInfo.getNickName())
				.sex(userInfo.getSex())
				.address(userInfo.getAddress())
				.email(userInfo.getEmail())
				.company(userInfo.getCompany())
				.recognizeStatus(userInfo.getRecognizeStatus())
				.build();
	}

	@Override
	@Cacheable(value = CacheConstants.USER_DETAILS_MINI, key = "#userId", unless = "#result == null")
	public OilUser findById(Long userId) {
		return this.getById(userId);
	}

	private OilUser findByOpenId(String openId) {
		AssertUtil.notEmpty(openId, "openId无效");

		LambdaQueryWrapper<OilUser> lambdaQuery = Wrappers.lambdaQuery();
		lambdaQuery.eq(OilUser::getOpenId, openId);
		List<OilUser> list = this.list(lambdaQuery);
		if (list.isEmpty()) {
			return null;
		} else {
			return list.get(0);
		}
	}

	@Override
	public OilUserSimpleVo getSimpleUserInfoByPhone(String phoneNumber) {
		Optional.ofNullable(phoneNumber).orElseThrow(() -> new BusinessException("电话号码为空"));
		LambdaQueryWrapper<OilUser> lambdaQuery = Wrappers.lambdaQuery();
		lambdaQuery.eq(OilUser::getPhone, phoneNumber);
		OilUser userInfo = this.getOne(lambdaQuery);
		if(null != userInfo){
			return OilUserSimpleVo.builder().phone(userInfo.getPhone()).userName(userInfo.getUserName()).build();
		}
		return null;
	}

}
